home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 5 / QRZ Ham Radio Callsign Database - Volume 5.iso / files / amiga / csrc720j.lzh / mbfwd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-18  |  32.5 KB  |  1,464 lines

  1. /*  Try to make this store all collection list in script to save I/O.
  2.  *  MBFWD.C - 6/28/91 - Autoforwarding.
  3.  *
  4.  *  The target port mode is set to idle if not connected,
  5.  *  set to remote if connected. It is set to disconnect or timeout
  6.  *  by getdat(), but this is checked and fixed up in getln().
  7.  *
  8.  *  All port input is through getln().
  9.  *  All file input is through nxtin().
  10.  */
  11.  
  12. #include "mb.h"
  13.  
  14. #ifdef MCH_AMIGA
  15. unsigned short all_number = 0;
  16. extern char fbb_direction,conn_direction;
  17. extern short debug;
  18. extern char tmpstr[];
  19. extern char passchr,hfstream,vhfstream;
  20. FILE *tmp_file;  /*FIX 9*/
  21. extern short thebox,kambbs;
  22. extern char hostport;
  23. #define deepmax    5     /* Max nesting depth of indirection in fwd.mb */
  24. #else
  25. #define deepmax    8     /* Max nesting depth of indirection in fwd.mb */
  26. #endif
  27.  
  28. #define fw_one     0x0001  /* Forward to only one MailBox, given in fcall*/
  29. #define fw_anytime 0x0002  /* Ignore the times in the "G" item           */
  30. #define fw_abort   0x0004  /* Abort forwarding as soon as possible       */
  31. #define fw_tried   0x0008  /* Attempted to forward to this MailBox       */
  32. #define fw_tiout   0x0010  /* Forward timeout flag                       */
  33. #define fw_forced  0x0020  /* Forced forward flag                        */
  34. #define fw_pass    0x0040  /* Bypass forward sub file                    */
  35. #define fw_idle    0x0080  /* Manual forward to idle                     */
  36. #define fw_ecall   0x0100  /* Forced forward ecall                       */
  37.  
  38. char  *script;           /* Pointer to where the connect script is     */
  39.  
  40. word  fopts;             /* Options, see defines above.                */
  41. char  fwdtyp;
  42. char  *fwdfile;          /* The file name of fwd.mb root file          */
  43. FILE  *ifl[deepmax];     /* File variables for fwd.mb                  */
  44. short deep;              /* Current depth within fwd.mb                */
  45. char  path[80];          /* "G" item saved here, for logging           */
  46. char  fcall[10];         /* Call of the MailBox to forward to          */
  47.  
  48. /*
  49.  *  YF command: change the name of the forwarding root file.
  50.  */
  51.  
  52. newfwd()
  53. {
  54.    if(*port->fld[1]) {
  55. #ifdef MCH_AMIGA
  56. /* FIX 9 */
  57. /* complain if specified fwdfile can't be found */
  58.       if((tmp_file = fopen(port->fld[1],"r")) == NULL) {
  59.          sprintf(tmp->scr,"can't find %s\n",port->fld[1]);
  60.          outstr(tmp->scr);
  61.       }
  62.       else {
  63.          fclose(tmp_file);
  64. #endif
  65.          free(fwdfile);
  66.          fwdfile = strdup(port->fld[1]);
  67. #ifdef MCH_AMIGA
  68.          titles();
  69.       }
  70. #endif
  71.    }
  72.    sprintf(tmp->scr, "is %s\n", fwdfile);
  73.    outstr(tmp->scr);
  74. }
  75.  
  76. /*
  77.  *  YF forward command: change the name of the forwarding root file.
  78.  */
  79.  
  80. newffwd()
  81. {
  82.    if(*cport->fld[1]) {
  83.       free(fwdfile);
  84.       fwdfile = strdup(cport->fld[1]);
  85.    }
  86. #ifndef MCH_AMIGA
  87.    printf("<File is %s>\n", fwdfile);
  88. #else
  89.    titles();
  90. #endif
  91. }
  92.  
  93. /*
  94.  *  Add a call to the list of BBS that have messages to be forwarded to them.
  95.  */
  96.  
  97. addbfwd(cp)
  98. char *cp;
  99. {
  100.    register short i;
  101.    register char *lp;
  102.  
  103.    for(i = 0, lp = bfwd; i < bfwdn; i++, lp += ln_call)
  104.       if(matchn(cp, lp, ln_call))
  105.          return;
  106.  
  107.    if(bfwdn < bfwdm) {
  108.       strncpy(lp, cp, ln_call);
  109.       bfwdn++;
  110.    }
  111. }
  112.  
  113. /*
  114.  *  Add a call to the list of users that have unread messges.
  115.  */
  116.  
  117. addufwd(cp)
  118. char *cp;
  119. {
  120.    register short i;
  121.    register char *lp;
  122.  
  123.    for(i = 0, lp = ufwd; i < ufwdn; i++, lp += ln_call)
  124.       if(matchn(cp, lp, ln_call))
  125.          return;
  126.  
  127.    if(ufwdn < ufwdm) {
  128.       strncpy(lp, cp, ln_call);
  129.       ufwdn++;
  130.    }
  131. }
  132.  
  133. /*
  134.  *  Check if a call has a message to be forwarded to it.
  135.  */
  136.  
  137. findfwd(cp, lp, n)
  138. char *cp, *lp;
  139. short n;
  140. {
  141.    register short i;
  142.  
  143.    for(i = 0; i < n; i++, lp += ln_call)
  144.       if(wcm(cp, lp))
  145.          return true;
  146.    return false;
  147. }
  148.  
  149. /*
  150.  *  Add the info from one message header to the lists of calls
  151.  *  of stations that have messages to be forwarded to them.
  152.  *
  153.  *  ufwd - Calls to put in beacon line.
  154.  *  bfwd - Calls that have message TO or AT.
  155.  */
  156.  
  157. addfwd()
  158. {
  159.    register short i;
  160.    char *p, hcall[6];
  161.  
  162.    if(!(port->mmhs->stat & (m_busy | m_kill | m_read | m_fwd | m_hold))) {
  163.       if(*port->mmhs->bbs is ' ') {
  164.          addufwd(port->mmhs->to);
  165.          addbfwd(port->mmhs->to);
  166.       }
  167.       else {
  168.          if(port->mmhs->ext is 1) {
  169.              for(i = 0; i < port->mmhs->count; i++) if (port->mmhs->flag[i])
  170.                 addbfwd(port->mmhs->call[i]);
  171.          }
  172.          else {
  173.             if(matchn(port->mmhs->bbs, cport->user->call, ln_call))
  174.                 addufwd(port->mmhs->to);
  175.             else
  176.                 addbfwd(port->mmhs->bbs);
  177.             if(port->mmhs->ext is 2) {
  178.                p = port->mmhs->call[0];
  179.                while((p = strchr(p, '.')) isnt NULL) {
  180.                   p++;
  181.                   fill(hcall, ' ', ln_call);
  182.                   pcall(hcall, p);
  183.                   addbfwd(hcall);
  184.                }
  185.             }
  186.          }
  187.       }
  188.    }
  189. }
  190.  
  191. /*
  192.  *  Build the two lists of calls of stations that have
  193.  *  messages to be forwarded to them.
  194.  */
  195.  
  196. bldfwd()
  197. {
  198.    register word  h;
  199.  
  200.    ufwdn = 0;
  201.    bfwdn = 0;
  202.    read_rec(mfl, 0, (char *)mfhs);
  203. #ifdef MCH_AMIGA
  204.    check_mail();
  205.    unlock_mail();
  206. #endif
  207.    for(h = mfhs->last; h; h--) {
  208.       read_rec(mfl, h, (char *)port->mmhs);
  209.       if(!(port->mmhs->stat & (m_busy|m_kill|m_read|m_fwd|m_hold)))
  210.          addfwd();
  211. #ifdef MCH_AMIGA
  212. /* Find highest numbered message to ALL which isn't busy, killed or held */
  213.       if(!(port->mmhs->stat & (m_busy | m_kill | m_hold)))
  214.           if(matchn("ALL        ",port->mmhs->to,ln_call))
  215.              if(port->mmhs->number > all_number) {
  216.                 all_number = port->mmhs->number;
  217.              }
  218. #endif
  219.    }
  220. }
  221.  
  222. /*
  223.  *  Return true if the current time is within
  224.  *  the time window for forwarding to this MailBox.
  225.  */
  226.  
  227. chktime()
  228. {
  229.    register short c, en, st;
  230.  
  231.    if(fopts & fw_anytime) return true;
  232.    curtim();
  233.    st = 10 * (int)(cport->line[2] - '0') + (int)(cport->line[3] - '0');
  234.    en = 10 * (int)(cport->line[4] - '0') + (int)(cport->line[5] - '0');
  235.    c  = 10 * (int)(l_time[0] - '0') + (int)(l_time[1] - '0');
  236.    if(st <= en)
  237.       return ((c >= st) and (c <= en));
  238.    return ((c >= st) or (c <= en));
  239. }
  240.  
  241. /*
  242.  *  Check if it is ok to forward using this list.
  243.  *  Return a pointer to the port to use for forwarding, or NULL.
  244.  */
  245.  
  246. PORTS *chkfwd()
  247. {
  248.    register PORTS *p;
  249.  
  250.    if(fopts & fw_one)
  251.       if(!match (fcall, cport->fld[1]))    { passlst(); return NULL; }
  252.    if(!chktime())                          { passlst(); return NULL; }
  253.    if((p = findport(cport->opt2)) is NULL) { passlst(); return NULL; }
  254.    if(!(p->flags & p_dofwd))               { passlst(); return NULL; }
  255.    if(fopts & fw_abort)                    { passlst(); return NULL; }
  256.    p->mode = idle;
  257.    return p;
  258. }
  259.  
  260. /*
  261.  *  Check if a disconnect happened.
  262.  */
  263.  
  264. chkdis()
  265. {
  266.    if(instat())
  267.       if(getdat())
  268.          if(isdis(port->line)) {
  269.             cmdtnc();
  270.             port->mode = idle;
  271.             return true;
  272.          }
  273.    if(port->flags & p_trans)
  274.       if(!isdcd()) {
  275.          cmdtnc();
  276.          port->mode = idle;
  277.          return true;
  278.       }
  279.    return false;
  280. }
  281.  
  282. /*
  283.  *  Read the next input line from FWD.MB,
  284.  *  or from a file referenced from FWD.MB.
  285.  *  Return NULL if no more lines to read.
  286.  */
  287.  
  288. char *nxtin(p)
  289. char *p;
  290. {
  291.    register char *st, i;
  292.  
  293.    while(deep >= 0) {
  294.       i = 1;
  295.       if((st = fgets(p, 80, ifl[deep])) is NULL) {
  296.          fclose(ifl[deep]);
  297.          deep--;
  298.       }
  299.       else {
  300.          if(*p isnt '@') return st;
  301.          if(fopts & fw_pass) return st;
  302.          if(*(p+1) is ' ') {
  303.             if(!chktime()) return st;
  304.             i = 6;
  305.          }
  306.          if(deep < (deepmax - 1)) {
  307.             strupr(p);
  308.             remnl(p);
  309.             deep++;
  310.             if((ifl[deep] = fopen(p + i, "r")) is NULL) deep--;
  311.          }
  312.       }
  313.    }
  314.    return NULL;
  315. }
  316.  
  317. /*
  318.  *  Do some DOS commands.
  319.  */
  320.  
  321.  
  322. dofdos()
  323. {
  324.    register PORTS *p;
  325.  
  326.    if((p = findport(cport->opt2)) is NULL) {
  327.       passlst();
  328.       return;
  329.    }
  330. #ifdef MCH_AMIGA
  331. /* Don't do this if the port doesn't forward! */
  332.    if((p->flags & p_dofwd) == 0) {
  333.       passlst();
  334.       return;
  335.    }
  336. #endif
  337.    if(strlen(cport->fld[0]) > 3)
  338.       if(!chktime()) {
  339.          passlst();
  340.          return;
  341.       }
  342.    if(fopts & fw_forced)
  343.       if(!((fopts & fw_one) and (match(fcall, cport->fld[1])))) {
  344.          passlst();
  345.          return;
  346.       }
  347.  
  348. /*
  349.  *  Just in case, flush whatever might be currently open.
  350.  */
  351.  
  352.    clnuser();
  353.    clnmsg();
  354.    clnlog();
  355.  
  356.    while(nxtin(cport->line) isnt NULL) {
  357.       if(iseof(cport->line)) return;
  358.       remnl(cport->line);
  359. #ifndef MCH_AMIGA
  360.       printf("\nRunning: %s\n", cport->line);
  361.       if(system(cport->line)) perror("Error");
  362. #else
  363.       sprintf(tmpstr,"\nRunning: %s\n", cport->line);
  364.       ttputs(tmpstr);
  365.       /* MANX doesn't like above syntax ..
  366.          gotta explicitly generate address
  367.       */
  368.       if(do_system(&cport->line[0])) perror("Error");
  369. #endif
  370.    }
  371. }
  372.  
  373. /*
  374.  *  The entry to fowarding.
  375.  */
  376. #ifdef MCH_AMIGA
  377. /* Temporarily avoid the problem of using tmp->scr */
  378. char callist[1200];
  379. #endif
  380. fwd()
  381. {
  382.    register PORTS *p;
  383. #ifdef MCH_AMIGA
  384.    register char *cp,*st;
  385. #endif
  386.  
  387. /*
  388.  *  If no fwd.mb file, then do nothing.
  389.  */
  390.    deep = 0;
  391.    if ((ifl[deep] = fopen(fwdfile, "r")) is NULL) return;
  392.  
  393.    bldfwd();
  394.  
  395.    script = tmp->scr;
  396.    *script = '\0';
  397.  
  398.    while(nxtin(cport->line) isnt NULL) {
  399. #ifdef MCH_AMIGA
  400.       kambbs = thebox = 0;
  401.       if(!fbb_direction)s_mart = 0;
  402. #else
  403.       s_mart = 0;
  404. #endif
  405.       ioport(cport);
  406.       strupr(cport->line);
  407.       parse();
  408.       fwdtyp = cport->opt1;
  409.       switch(fwdtyp) {
  410.       case 'E':
  411.          passlst();
  412.          script = tmp->scr;
  413.          *script = '\0';
  414.          break;
  415.       case 'D':
  416.       case 'F':
  417.       case 'G':
  418.       case 'H':
  419.          if((p = chkfwd()) isnt NULL) {
  420.             fopts clrbit fw_tried;
  421. /*
  422.  *  Save tail of list header for logging.
  423.  */
  424.             strcpy(path, cport->line + 6);
  425.             remnl(path);
  426. #ifndef MCH_AMIGA
  427.             strcpy(fcall, cport->fld[1]);
  428. #else
  429.             pcall(fcall,cport->fld[1]);
  430. #endif
  431.             script = tmp->scr;
  432.             if(!*script) {
  433.                *script = 'C';
  434.                strcpy(script + 1, cport->line + 6);
  435.                *(script + strlen(script) + 1) = '\0';
  436.             }
  437. #ifndef MCH_AMIGA
  438.             dofwd(p);
  439.             dorev(p);
  440. #else
  441.             /* callist points to start of call collection list
  442.                Read all of the calls for this station into memory.
  443.                This allows me to make one pass through the mail.dat file
  444.                instead of one pass for each call that does have outgoing
  445.                mail.
  446.             */
  447.            /* callist = script + strlen(script)+1; */
  448.             callist[0] = 0;
  449.             st = nxtin(cport->line);
  450.             /* Check for the filesize limiter */
  451.             filesize = 0;
  452.             if(*cport->line == '<') {
  453.                if(chktime())
  454.                   if(!(fopts & fw_anytime))
  455.                      filesize = atoi(&cport->line[6]);
  456.                st = nxtin(cport->line);
  457.             }
  458.             cp = callist;
  459.             if(fopts & fw_ecall) {
  460.                pcall(cp,tcall);
  461.                cp += ln_call;
  462.                *cp = 0;
  463.             }
  464.             while(!iseof(cport->line) and (st isnt NULL)) {
  465.  
  466.                pcall(cp,cport->line);
  467.                cp += ln_call;
  468.                *cp = 0;
  469.                st = nxtin(cport->line);
  470.             }
  471.             user_title(fcall);
  472.             /* chkfwd() forces idle ... have to set it to remote for
  473.                a BBS which has called us
  474.             */
  475.             if(fbb_direction)p->mode = remote;
  476.             dofwd(p);
  477.             if((s_mart & fbbok) == 0) {
  478.                dorev(p);
  479.             }
  480.             user_title("");
  481. #endif
  482.             distnc();
  483.             p->mode = idle;
  484.             ioport(cport);
  485.          }
  486.          script = tmp->scr;
  487.          *script = '\0';
  488.          break;
  489.  
  490.       case 'P':
  491.          dopar();
  492.          break;
  493.  
  494.       case '!':
  495.          dofdos();
  496.          break;
  497.  
  498.       case 'Y':
  499. #ifdef MCH_AMIGA
  500. /* Only do the 'YF' at the end of the file if this is NOT the console
  501.    port forwarding time
  502. */
  503.          if((cport->flags & p_dofwd) == 0)
  504. #endif
  505.          if((cport->opt2 is 'F') and (chktime() ))
  506.             newffwd();
  507.          break;
  508.  
  509.       case 'C':
  510.       case 'R':
  511.       case 'S':
  512.          strcpy(script, cport->line);
  513.          script += (strlen(cport->line) + 1);
  514.          *script = '\0';
  515.          break;
  516.  
  517.       default:
  518.          break;
  519.       }
  520.    }
  521.  
  522. /*
  523.  *  Put us back on the port we were on when we got here.
  524.  */
  525.  
  526.    ioport(cport);
  527. #ifdef MCH_AMIGA
  528.    kambbs = thebox = 0;
  529.    conn_direction = ' ';
  530.    user_title("");
  531. #endif
  532.    s_mart = 0;
  533. }
  534.  
  535. /*
  536.  *  A and AI commands.
  537.  */
  538.  
  539. #ifndef MCH_AMIGA
  540. /* Moved to mb.c so I don't have to make a SYSOP version of mbfwd just for
  541.    this one routine
  542. */
  543. all_fwd()
  544. {
  545.    word pflg;
  546.    port->opt1 = 'X';
  547.    putcomd( port->opt1, port->opt2 );
  548.  
  549.    pflg = getp_flag();
  550.    putc_flag (pflg);
  551.    port->mode = logout;
  552. }
  553. #endif
  554.  
  555. /*
  556.  *  X and XI commands.
  557.  */
  558.  
  559. sfwd()
  560. {
  561.    register PORTS *p;
  562.  
  563. /*
  564.  *  If remote sysop did the command, just remember it for later.
  565.  */
  566.  
  567.    if(port->mode & sysop) {
  568.       savecmd();
  569.       return;
  570.    }
  571.  
  572. /*
  573.  *  Set up parameters for fwd()
  574.  */
  575.  
  576.    fopts = fw_forced;
  577.    for(p = porthd; p isnt NULL; p = p->next) {
  578.       p->ec = p->ecuser;
  579.       p->flags setbit p_dofwd;
  580.    }
  581.  
  582.    if(cport->flds > 1) {
  583.       fopts setbit fw_one;
  584.       strncpy (fcall, cport->fld[1], ln_callp);
  585.    }
  586.    if(cport->flds is 3) {
  587.       fopts setbit fw_ecall;
  588.       pcall(tcall, cport->fld[2]);
  589.    }
  590.  
  591.    if((cport->opt2 is 'I')or(cport->opt2 is 'B'))
  592.       fopts setbit fw_anytime;
  593.    if(cport->opt2 is 'B')
  594.       fopts setbit fw_idle;
  595. #ifdef MCH_AMIGA
  596.    conn_direction = '>';
  597. /* Tell fbb that we called */
  598.    fbb_direction = 0;
  599. #endif
  600.    fwd();
  601.  
  602. /*
  603.  *  Reset the port flags.
  604.  */
  605.  
  606.    for(p = porthd; p isnt NULL; p = p->next)  {
  607.       p->ec = p->ecmon;
  608.       p->flags clrbit p_dofwd;
  609.    }
  610.    if(fopts & fw_idle) bye();
  611.  
  612. }
  613.  
  614. /*
  615.  *  Automatic forwarding.
  616.  *  Called once each minute when the MailBox is idle.
  617.  */
  618.  
  619. afwd(curmin)
  620. int curmin;
  621. {
  622.    register PORTS *p;
  623.    register short anyfwd;
  624.  
  625. #ifdef MCH_AMIGA
  626. /* FIX 14 The setunt routine can be called with the TNC as the port
  627.           and in that case it will send all output from an automatic
  628.           untangle to the TNC as well as the console.
  629. */
  630.    register PORTS *saveport;
  631.  
  632.    saveport = port;
  633.    conn_direction = '>';
  634. /* Tell fbb that we called */
  635.    fbb_direction = 0;
  636. #endif
  637.  
  638. /*
  639.  *  Mark the ports that should forward at this minute.
  640.  */
  641.  
  642.    fopts = 0;
  643.    anyfwd = false;
  644.    for(p = porthd; p isnt NULL; p = p->next)
  645.       if(p->fwdmin is curmin) {
  646.  
  647. #ifdef MCH_AMIGA
  648. /* Console only forwards from the process running port A */
  649.          if((p->id == 'Z') && (hostport != 'A'))continue;
  650. #endif
  651.  
  652.          p->flags setbit p_dofwd;
  653.          p->ec = p->ecuser;
  654.          anyfwd = true;
  655.       }
  656.  
  657. /*
  658.  *  If any ports forward at this minute, do the forwarding.
  659.  */
  660.  
  661.    if(anyfwd) {
  662.       setbusy();
  663.       alloff();   /* Turn off connects and monitoring */
  664.       if(s_flag & s_dv) begin_lock();
  665.       readmsg();
  666.       readusr();
  667.  
  668. /*
  669.  *  Write out mon and calls heard files
  670.  */
  671.       clsmon();
  672.  
  673. /*
  674.  *  Once a day, do wp and stale
  675.  */
  676.       if(!matchn(ufhs->wpdate, l_date, ln_date)) {
  677.          port->opt1 = '\0';
  678.          port->flds = 1;
  679.          if(s_flag & s_dv) end_lock();
  680. #ifdef MCH_AMIGA
  681.          lock_user();
  682. #endif
  683.          dwuser();
  684.          if(s_flag & s_dv) begin_lock();
  685.          stale();
  686.          strncpy(ufhs->wpdate, l_date, ln_date);
  687.          write_rec(ufl, 0, (char *)ufhs);
  688. #ifdef MCH_AMIGA
  689.          unlock_user();
  690. #endif
  691.       }
  692.       if(s_flag & s_dv) end_lock();
  693.  
  694. /*
  695.  * Check and see if the mailfile should be compressed
  696.  */
  697.       if(s_param & s_unt)
  698.       if(!matchn(mfhs->date, l_date, ln_date))
  699.       if(unt_hr <= (10 *(l_time[0] - '0') + (l_time[1] - '0')))
  700.       {
  701. #ifdef MCH_AMIGA
  702.          ioport(cport);
  703. #endif
  704.          port->opt2 = 'A';
  705.          setunt();
  706. #ifdef MCH_AMIGA
  707.          ioport(saveport);
  708. #endif
  709.       }
  710.  
  711.       fwd();
  712.       clnlog();
  713.       setfwd();
  714.       clsmsg();
  715.       clsusr();
  716.       allon();    /* Turn on monitoring and connects */
  717.       clrbusy();
  718.    }
  719.  
  720. /*
  721.  *  Reset the port flags.
  722.  */
  723.  
  724.    for(p = porthd; p isnt NULL; p = p->next) {
  725.       p->ec = p->ecmon;
  726.       p->flags clrbit p_dofwd;
  727.    }
  728. }
  729.  
  730. /*
  731.  *  Reverse forwarding.
  732.  *  Accept messages from the remote MailBox after forwarding to it.
  733.  */
  734.  
  735. dorev(p)
  736. PORTS *p;
  737. {
  738.    char rcall[6];
  739.  
  740.    ioport(p);
  741.    if(fwdtyp is 'G') return;
  742.    if(fwdtyp is 'D') return;
  743.  
  744.    if(p->mode & idle) {
  745.       if(fwdtyp is 'F')
  746.          return;
  747.       if(fwdtyp is 'H')
  748.          if(fopts & fw_tried)
  749.             return;
  750.       cmb();
  751.       if(p->mode & idle) return;
  752.    }
  753.  
  754.    pcall(rcall, path + 2);
  755.    rduser(rcall, p->user);
  756.    log('M', 'F', 'R', path);  /* Log start of reverse forward */
  757. #ifdef MCH_AMIGA
  758.    user_title(p->user->call);
  759.    /* dorev can be called if dofwd does not find anything to send!
  760.       Call fbbfwd before setting transparent mode ... it's done in
  761.       fbbfwd.
  762.    */
  763.    if(s_mart & fbbok) {
  764.       fbb_direction = 0;
  765.       fbbfwd(0);
  766.       return;
  767.    }
  768.  
  769. #endif
  770.  
  771.    if(p->tmode) {
  772.       cmdtnc();
  773.       trantnc();
  774.    }
  775.  
  776.    while(true) {
  777.       outstr("F>\n");
  778.       getln();
  779.       if(p->mode & idle) return;
  780.       parse();
  781.  
  782.       if(p->opt1 isnt 'S') return;
  783.       sndmsg();
  784.       if(p->mode & gone) return;
  785.       addfwd();
  786.    }
  787. }
  788.  
  789. /*
  790.  *  F> command: do reverse forward to logged user.
  791.  */
  792.  
  793. fwdcmd()
  794. {
  795.    register PORTS *p;
  796.    register short ok;
  797. #ifdef MCH_AMIGA
  798.    register char *st,*cp;
  799. #endif
  800.  
  801. /*
  802.  *  If no fwd.mb file, then do nothing.
  803.  */
  804.  
  805.    p = port;
  806.    deep = 0;
  807.    if((ifl[deep] = fopen(fwdfile, "r")) is NULL) {
  808.       p->mode = forced;
  809.       return;
  810.    }
  811.  
  812.    ioport(cport);
  813.  
  814. /*
  815.  *  Find the users E, F, G, or H list in the fwd.mb file.
  816.  */
  817.  
  818.    ok = false;
  819.    while(!ok and (nxtin(cport->line) isnt NULL)) {
  820.       strupr(cport->line);
  821.       parse();
  822.       fwdtyp = cport->opt1;
  823.  
  824.       switch(fwdtyp) {
  825.       case 'D':
  826.       case 'E':
  827.       case 'F':
  828.       case 'G':
  829.       case 'H':
  830.          pcall(fcall, cport->fld[1]);
  831.          ok = matchn(fcall, p->user->call, ln_call);
  832.  
  833.          if (!ok) passlst();
  834. #ifdef MCH_AMIGA
  835.          else {
  836.             /*  callist = script + strlen(script)+1; */
  837.             st = nxtin(cport->line);
  838.             /* Check for the filesize limiter */
  839.             filesize = 0;
  840.             callist[0] = 0;
  841.             if(*cport->line == '<') {
  842.                if(chktime())
  843.                   if(!(fopts & fw_anytime))
  844.                      filesize = atoi(&cport->line[6]);
  845.                st = nxtin(cport->line);
  846.             }
  847.             cp = callist;
  848.             if(fopts & fw_ecall) {
  849.                pcall(cp,tcall);
  850.                cp += 6;
  851.                *cp = 0;
  852.             }
  853.             while(!iseof(cport->line) and (st isnt NULL)) {
  854.                pcall(cp,cport->line);
  855.                cp += 6;
  856.                *cp = 0;
  857.                st = nxtin(cport->line);
  858.             }
  859.          }
  860. #endif
  861.          break;
  862.  
  863.       case '!':
  864.       case 'P':
  865.          passlst();
  866.          break;
  867.  
  868.       default  : ;   /* 'C', 'R', 'S', 'Y' */
  869.       }
  870.    }
  871.  
  872.    ioport(p);
  873.  
  874.    if(ok) {
  875.       log ('M', 'F', 'S', nullstr);      /* Log start of forwarding */
  876.       bldfwd();
  877.       remnl(cport->line);
  878.       strcpy( path, cport->line+6 );
  879.       dofwd(p);
  880.       log ('M', 'F', 'E', nullstr);      /* Log end of forwarding */
  881.    }
  882.  
  883.    while(deep >= 0) {
  884.       fclose(ifl[deep]);
  885.       deep--;
  886.    }
  887.    if(p->mode is idle) return;
  888. #ifndef MCH_AMIGA
  889.    outstr("*** Done.\n");
  890. #else
  891.    /* It seems that some BBS do not like "Done" so we'll just drop out */
  892.    distnc();
  893. #endif
  894. }
  895.  
  896. /*
  897.  *  Pass a sublist in the forwarding file.
  898.  */
  899.  
  900. passlst()
  901. {
  902.    fopts setbit fw_pass;
  903.    while(true) {
  904.       if(nxtin(cport->line) is NULL) {
  905.          fopts clrbit fw_pass;
  906.          return;
  907.       }
  908.       if(iseof(cport->line)) {
  909.          fopts clrbit fw_pass;
  910.          return;
  911.       }
  912.    }
  913. }
  914.  
  915. /*
  916.  *  Set tnc parameters.
  917.  */
  918.  
  919. dopar()
  920. {
  921.    register PORTS *p;
  922.  
  923.    if((p = findport(cport->opt2)) is NULL) {
  924.       passlst();
  925.       return;
  926.    }
  927. #ifdef MCH_AMIGA
  928. /* Don't do this if the port doesn't forward at this time */
  929.    if((p->flags & p_dofwd) == 0) {
  930.       passlst();
  931.       return;
  932.    }
  933. #endif
  934.  
  935.    if(strlen(cport->fld[0]) > 3)
  936.       if(!chktime()) {
  937.          passlst();
  938.          return;
  939.       }
  940.  
  941.    ioport(p);
  942.    while(nxtin(cport->line) isnt NULL) {
  943.       if(iseof(cport->line)) {
  944.          ioport(cport);
  945.          return;
  946.       }
  947.       onetnc(cport->line);
  948.    }
  949.    ioport(cport);
  950. }
  951.  
  952. /*
  953.  *  Get a line from the current port.
  954.  *  Handle disconnect, timeout, and ^F.
  955.  */
  956.  
  957. getln()
  958. {
  959.    while(!getdat());
  960.    if(port->mode & forced) fopts setbit fw_abort;
  961.    if(port->mode & gone) {
  962.       distnc();
  963.       port->mode = idle;
  964.    }
  965. }
  966.  
  967. /*
  968.  *  Eat the remote MailBox prompt.
  969.  */
  970.  
  971. eat()
  972. {
  973.    register char c;
  974.    if(fwdtyp is 'D') c = ':';
  975.    else              c = '>';
  976.    while(true) {
  977.       getln();
  978.       if(!(port->mode & remote)) return;
  979.       if(port->line[0] is '[') isbid();
  980.       if((port->mode & remote) and
  981.                              (port->line[strlen(port->line) - 2] is c)) {
  982.          return;
  983.     }
  984.   } 
  985. }
  986.  
  987. /*
  988.  *  Connect to a remote Mailox.
  989.  *  Port mode idle at entry.
  990.  *  On return, port mode is remote if the connect worked, else idle.
  991.  */
  992.  
  993. cmb()
  994. {
  995.    port->flags setbit p_dotmr;
  996.    port->mode = remote;
  997.  
  998. /*
  999.  * Execute the connect script.
  1000.  */
  1001.    while(*script) {
  1002.       switch(*script++) {
  1003.       case 'C':
  1004.          contnc(script);
  1005.          if(port->mode & idle) return;
  1006.          if(port->dev is p_tnc)
  1007.             do {
  1008.                getln();
  1009.                if(port->mode & idle) return;
  1010.             }
  1011.          while(!iscon(port->line));
  1012.          break;
  1013.  
  1014.       case 'S':
  1015.          outstr(script);
  1016.          break;
  1017.  
  1018.       case 'R':
  1019.          getln();
  1020.          if(port->mode & idle) return;
  1021.          strupr(port->line);
  1022.          if(*script isnt '!')
  1023. #ifndef MCH_AMIGA
  1024.             if(!search(port->line, script, strlen(script)-1))
  1025. #else
  1026. /* The new Manx 5.0 compiler uses a LONG for strlen AND for
  1027.    sizeof so must change things a bit
  1028. */
  1029.             if(!search(port->line, script, (short)strlen(script)-1))
  1030. #endif
  1031.             {
  1032.                distnc();
  1033.                port->mode = idle;
  1034.                return;
  1035.             }
  1036.          break;
  1037.  
  1038.       default: ;
  1039.       }
  1040.       while(*script++);  /* Move to next script line */
  1041.    }
  1042.  
  1043. /*
  1044.  *  In theory, now connected to MailBox. Eat login messge.
  1045.  */
  1046.  
  1047.    eat();
  1048.    if(!(port->mode & remote)) return;
  1049.    if(s_mart) {
  1050.       outstr(vers);
  1051. #ifdef MCH_AMIGA
  1052. /* If we called them and they are an fbb system, don't call eat().
  1053. */
  1054.       if(s_mart & fbbok) {
  1055.          return;
  1056.       }
  1057. #endif
  1058.       eat();
  1059.    }
  1060. }
  1061.  
  1062. /*
  1063.  *  Forward whatever messages go to this MailBox.
  1064.  */
  1065.  
  1066. dofwd(p)
  1067. PORTS *p;
  1068. {
  1069.    register char *st;
  1070.    ioport(p);
  1071.    fmsg();
  1072.    if(fopts & fw_tried) {
  1073.       if(p->mode & idle) {
  1074.          p->mmhs->stat clrbit m_busy;
  1075.          wt_mmhs();
  1076. #ifndef MCH_AMIGA
  1077. /* Can't do passlst here any more. We are already at the end of the list*/
  1078.          passlst();
  1079. #endif
  1080.          return ;
  1081.       }
  1082.    }
  1083. }
  1084.  
  1085. /*
  1086.  *  Send the message text.
  1087.  */
  1088.  
  1089. xmtmsg()
  1090. {
  1091.    register FILE *fl;
  1092. #ifdef MCH_AMIGA
  1093.    register char *cp,*pp;
  1094. #endif
  1095.  
  1096.    sprintf(port->line, "%s%u", msgdir, port->mmhs->number);
  1097.    if((fl = fopen(port->line, "r")) is NULL)
  1098.       nofile(port->line);
  1099.    else {
  1100.       fseek(fl, (long)RECSIZE, 0);
  1101.       while(fgets(tmp->scr, scrmax, fl) isnt NULL) {
  1102.          if(chkdis()) {
  1103.             fclose(fl);
  1104.             return false;
  1105.          }
  1106. #ifdef MCH_AMIGA
  1107.          for(cp = tmp->scr,pp = &tmpstr[0];
  1108.                                       *cp && (pp < &tmpstr[280]);cp++) {
  1109.             if(*cp == passchr)continue;
  1110.             /* insert the pass character for stream characters */
  1111.             if(passchr) {
  1112.                if((*cp == vhfstream) || (*cp == hfstream)) {
  1113.                   *pp++ = passchr;
  1114.                }
  1115.                *pp++ = *cp;
  1116.                continue;
  1117.             }
  1118.             if((*cp >= ' ') && (*cp <= 0176)) {
  1119.                *pp++ = *cp;
  1120.                continue;
  1121.             }
  1122.             /*
  1123.                Allow BEL BS HT LF VT FF and CR through.
  1124.                All others are omitted
  1125.             */
  1126.             if((*cp >= 7) && (*cp <= '\r')) {
  1127.                *pp++ = *cp;
  1128.                continue;
  1129.             }
  1130.          }
  1131.          *pp = 0;
  1132.          outstr(tmpstr);
  1133. #else
  1134.          outstr(tmp->scr);
  1135. #endif
  1136.       }
  1137.       fclose (fl);
  1138.    }
  1139.    if(fwdtyp is 'D') {
  1140.       outstr(".\n");
  1141.       outstr("y\n");
  1142.    }
  1143.    else {
  1144.       outchar(cpmeof);
  1145.       outchar('\n');
  1146.    }
  1147.    return true;
  1148. }
  1149.  
  1150. /*
  1151.  *  Forward all messages TO or AT tcall
  1152.  *  to the MailBox we are connected to.
  1153.  */
  1154.  
  1155. fmsg()
  1156. {
  1157.    char *a, *b, *c;
  1158.    char hcall[6];
  1159.    register PORTS *p;
  1160.    register word h;
  1161.    register short i, ok, extnr, hasit;
  1162.  
  1163.    hasit = true;   /* just initialize it to something */
  1164.  
  1165.    p = port;
  1166. #ifdef MCH_AMIGA
  1167.    check_mail();
  1168.    unlock_mail();
  1169. #endif
  1170.    for(h = mfhs->last; h; h--) {
  1171.       if(s_flag & s_dv) begin_lock();
  1172.       read_rec(mfl, h, (char *)p->mmhs);
  1173. #ifndef MCH_AMIGA
  1174. /* Put all this in check_ok() so that fbb can sort out whether to send a
  1175.    message or not
  1176. */
  1177.  
  1178.       ok = (!(p->mmhs->stat & (m_kill|m_read|m_fwd|m_hold|m_busy)));
  1179.  
  1180.       if(ok)
  1181.          if(filesize)
  1182.             ok = filesize > p->mmhs->size;
  1183. /*
  1184.  *  Decide whether to forward this one.
  1185.  */
  1186.       if(ok) {
  1187. #ifndef MCH_AMIGA
  1188.          if (p->mmhs->ext is 1)
  1189. #else
  1190. /* Fix bug. A bulletin should only be forwarded to the connected station
  1191.    IF and ONLY IF the connected station has not yet received it.
  1192.    This code sends it back to the calling station if one of the stations
  1193.    in the distribution list for the bulletin is also in the collection
  1194.    list for the connected station
  1195.  
  1196.    NOT SURE I'VE GOT THIS RIGHT SO I'VE TAKEN IT OUT AGAIN
  1197. */
  1198.          if((p->mmhs->ext == 1) /* && matchn(fcall,tcall,ln_call)*/)
  1199. #endif
  1200.          {
  1201.             ok = false;
  1202.             for(i = 0; !ok and (i < p->mmhs->count); i++)
  1203.                if(p->mmhs->flag[i])
  1204.                   if(wcm(tcall, p->mmhs->call[i])) {
  1205.                      ok = true;
  1206.                      extnr = i;
  1207.                   }
  1208.          }
  1209.          else if(*p->mmhs->bbs isnt ' ') {
  1210.             ok = wcm(tcall, p->mmhs->bbs);
  1211.             if(!ok) if(p->mmhs->ext is 2) {
  1212.                c = p->mmhs->call[0];
  1213.                while(!ok and ((c=strchr(c, '.')) isnt NULL)) {
  1214.                   c++;
  1215.                   fill(hcall, ' ', ln_call);
  1216.                   pcall(hcall, c);
  1217.                   ok = wcm(tcall, hcall);
  1218.                }
  1219.             }
  1220.          }
  1221.          else
  1222.             ok = wcm(tcall, p->mmhs->to);
  1223.       }
  1224. #else
  1225. /* kludge a way to get extnr passed through. check_ok returns extnr if it
  1226.    is set (which implies ok and -1 if ok but extnr not set. Zero otherwise.
  1227.    extnr is only used  if ->ext == 1  which is only way it could be set
  1228. */
  1229.       ok = check_ok();
  1230.       if(ok > 0)extnr = ok-1;
  1231.  
  1232. #endif
  1233.  
  1234.       if(ok) {
  1235.          p->mmhs->stat setbit m_busy;
  1236.          wt_mmhs();
  1237.       }
  1238.       if(s_flag & s_dv)
  1239.          end_lock();
  1240.  
  1241. /*
  1242.  *  If we DO forward this one, forward this one.
  1243.  */
  1244.       if(ok) {
  1245.          if(fopts & fw_tiout) {
  1246.             wait (p->ftime);
  1247.             fopts clrbit fw_tiout;
  1248.          }
  1249.          fopts setbit fw_tried;
  1250.          if(p->mode & idle) cmb();
  1251.          if(p->mode & idle) return;
  1252. #ifdef MCH_AMIGA
  1253.          if(s_mart & fbbok) {
  1254.          /* This is ugly .. have to release the first message to be sent so
  1255.             that fbbfwd can find it again. There's got to be a better way!
  1256.             But the forwarding routine doesn't do anything until it has
  1257.             found the first message to forward.
  1258.          */
  1259.             p->mmhs->stat clrbit m_busy;
  1260.             wt_mmhs();
  1261.             pcall(hcall, path + 2);
  1262.             rduser(hcall, p->user);
  1263.             fbbfwd(h);
  1264.             return;
  1265.          }
  1266. #endif
  1267. /*ttputs("FMSG\n");*/
  1268.          if(*p->mmhs->bbs is ' ')
  1269.             prtx("S$B $G < $P");
  1270.          else
  1271.             if((s_mart&hidok)and(p->mmhs->ext is 2))
  1272.                prtx("S$B $G @ $h < $P");
  1273.             else
  1274.                prtx("S$B $G @ $A < $P");
  1275. #ifndef MCH_AMIGA
  1276.          if(s_mart&bidok) if (*p->mmhs->bid isnt ' ') {
  1277. #else
  1278.          if(s_mart&(bidok|midok)) if (*p->mmhs->bid isnt ' ') {
  1279. #endif
  1280.             outstr(" $");
  1281.             a = p->line;
  1282.             b = p->mmhs->bid;
  1283.             unbl(a, b, ln_bid);
  1284.             outstr(p->line);
  1285.          }
  1286. #ifdef MCH_AMIGA
  1287. /* If we are talking to THEBOX and this message has a lifetime, then
  1288.    send the lifetime
  1289. */
  1290.          if(thebox && p->mmhs->lifetime) {
  1291.             sprintf(tmpstr," #%u",p->mmhs->lifetime);
  1292.             outstr(tmpstr);
  1293.          }
  1294. #endif
  1295.          outchar('\n');
  1296.          getln();
  1297.          if(p->mode & idle) return;
  1298.          if(s_mart) {
  1299.             if(*p->line < ' ') {
  1300.                getln();
  1301.                if(p->mode & idle) return;
  1302.             }
  1303.             switch(*p->line) {
  1304.             case 'O':
  1305.                hasit = false;
  1306.                outstr(p->mmhs->title);
  1307.                outchar('\n');
  1308.                break;
  1309.             case 'N':
  1310.                hasit = true;
  1311.                break;
  1312.             default:
  1313.                p->mmhs->stat clrbit m_busy;
  1314.                wt_mmhs();
  1315.                return;
  1316.             }
  1317.          }
  1318.          else {
  1319.             hasit = false;        /* you'll want to send msg */
  1320.             outstr(p->mmhs->title);
  1321.             outchar('\n');
  1322.             getln();
  1323.             if(p->mode & idle) return;
  1324.          }
  1325.          if(!hasit) {
  1326.             curtim();
  1327.             prtx(mm[4]);
  1328.             if(!xmtmsg()) {
  1329.                fopts setbit fw_tiout;
  1330.                return;
  1331.             }
  1332.          }
  1333.          eat();
  1334.          if(p->mode & idle) {
  1335.             fopts setbit fw_tiout;
  1336.             return;
  1337.          }
  1338. /*
  1339.  *  The message actually forwarded.
  1340.  *  Kill it, mark it, or whatever.
  1341.  */
  1342. if(debug)printf("MARKIT\n");
  1343.          sprintf(p->line, "%u %s", p->mmhs->number, path);
  1344.          log ('M', 'F', ' ', p->line);
  1345.        
  1346.          markdis(extnr);
  1347.  
  1348.          p->mmhs->stat clrbit m_busy;
  1349.          if(p->mmhs->ext isnt 1) {
  1350.             pcall(p->mmhs->fwdc, fcall);
  1351.             p->mmhs->fport = p->id;
  1352.          }
  1353.          write_rec(mfl, p->mmhs->rn, (char *)p->mmhs);
  1354.          makehdr2();
  1355.       }
  1356.    }
  1357. #ifdef MCH_AMIGA
  1358.    /* Only get here if the loop didn't find a message to send. But still
  1359.       have to call fbbfwd to receive stuff from the other end
  1360.    */
  1361.    if(s_mart & fbbok) {
  1362.       fbbfwd(0);
  1363.    }
  1364. #endif
  1365. }
  1366. markdis(nr)
  1367. int nr;
  1368. {
  1369.   int i, kill, kok;
  1370.   kill = false;
  1371.   kok = false;
  1372. /*  If cc: list exists, mark this call as forwarded. */
  1373.  
  1374.   if (port->mmhs->ext is 1)
  1375.   {
  1376.      port->mmhs->flag[nr] = false;
  1377.      for (i = 0; i < port->mmhs->count; i++)
  1378.      if (port->mmhs->flag[i]) kok = true;
  1379.   }
  1380.  
  1381.   if (!kok)
  1382.   {
  1383.      if ((port->mmhs->type is 'B') or (port->mmhs->ext is 1))
  1384.      kill = s_param & s_fkill;
  1385.      else kill = s_param & s_kill;
  1386.   }
  1387.  
  1388.   if (kill) port->mmhs->stat setbit m_kill;
  1389.   else if (!kok) port->mmhs->stat setbit m_fwd;
  1390.  
  1391. }
  1392. #ifdef MCH_AMIGA
  1393. check_ok()
  1394. {
  1395.    int ok,extnr;
  1396.    register int i;
  1397.    register char *cp;
  1398.    register char *c;
  1399.    register PORTS *p;
  1400.    char hcall[6];
  1401.  
  1402.  
  1403.    extnr = -1;
  1404.    p = port;
  1405.    ok = (!(p->mmhs->stat & (m_kill|m_read|m_fwd|m_hold|m_busy)));
  1406.    if (ok) if(filesize)  ok = filesize > p->mmhs->size;
  1407. /*   if(ok) ok = findfwd(tcall, bfwd, bfwdn); */
  1408. /*
  1409.  *  Decide whether to forward this one.
  1410.  */
  1411.    if(ok) {
  1412.       ok = false;
  1413.       for(cp = callist;*cp && !ok;cp+=ln_call) {
  1414.          strncpy(tcall,cp,ln_call);
  1415. /* Fix bug. A bulletin should only be forwarded to the connected station
  1416.    IF and ONLY IF the connected station has not yet received it.
  1417.    The old code sent it back to the calling station if one of the stations
  1418.    in the distribution list for the bulletin was also in the collection
  1419.    list for the connected station
  1420.    I've removed it. Not sure I've fixed it properly.
  1421. */
  1422.          if((p->mmhs->ext == 1)/* && matchn(fcall,tcall,ln_call)*/) {
  1423.             for (i = 0; !ok and (i < p->mmhs->count); i++)
  1424.                if (p->mmhs->flag[i])
  1425.                   if(wcm(tcall, p->mmhs->call[i])) {
  1426.                      ok = true;
  1427.                      extnr = i;
  1428.                   }
  1429.          }
  1430.          else if(*p->mmhs->bbs isnt ' ') {
  1431.             ok = wcm(tcall, p->mmhs->bbs);
  1432.             if(!ok)
  1433.                if(p->mmhs->ext is 2) {
  1434.                   c = p->mmhs->call[0];
  1435.                   while(!ok and ((c=strchr(c, '.')) isnt NULL)) {
  1436.                      c++;
  1437.                      fill(hcall, ' ', ln_call);
  1438.                      pcall(hcall, c);
  1439.                      ok = wcm(tcall, hcall);
  1440.                   }
  1441.                }
  1442.          }
  1443.          else {
  1444.             ok = wcm(tcall, p->mmhs->to);
  1445.          }
  1446. #ifdef MCH_AMIGA
  1447. /* If the TO field is a callsign and the connected BBS has them in its
  1448.    colection list, then send it anyway.
  1449. */
  1450.          if(!ok && iscall(p->mmhs->to))ok = wcm(tcall,p->mmhs->to);
  1451. #endif
  1452.       }
  1453.    }
  1454.    if(extnr >= 0) {
  1455. /* Have to return one more than extnr because it can be zero */
  1456.       return(extnr+1);
  1457.    }
  1458.    if(ok) {
  1459.       return(-1);
  1460.    }
  1461.    return(0);
  1462. }
  1463. #endif
  1464.